package com.hailiang.study.javase.java.util.concurrent;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;

/**
 * 并行执行一批任务，依次处理完成的任务结果(哪个任务先执行完就先处理哪个)。
 * @author hailiang.jiang
 * @date 2021年07月31 23:07
 */
public class CompletionService_take {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        // 创建两个任务
        Callable<Integer> task01 = () -> {
            TimeUnit.SECONDS.sleep(3);
            System.out.println(String.format("[%s] task01 finished", Thread.currentThread().getName()));
            return 1;
        };

        Callable<Integer> task02 = () -> {
            try {
                TimeUnit.SECONDS.sleep(10);
                System.out.println(String.format("[%s] task02 finished", Thread.currentThread().getName()));
            } catch (InterruptedException e) {
                // 第二个任务耗时长，等第一个任务完成之后，手动取消第二个任务的执行，此时第二个任务可能会收到中断。
                e.printStackTrace();
            }
            return 2;
        };

        List<Callable<Integer>> tasks = Arrays.asList(task01, task02);

        // 创建线程池
        ExecutorService pool = Executors.newFixedThreadPool(2);
        // 使用CompletionService批量提交任务
        CompletionService completionService = new ExecutorCompletionService<>(pool);

        List<Future> futures = new ArrayList<>();
        for (Callable<Integer> task : tasks) {
            Future fu = completionService.submit(task);
            futures.add(fu);
        }

        // 获取第一个执行完的任务结果
        Future take = completionService.take();
        System.out.println("[" + Thread.currentThread().getName() + "]" + take.get());
        futures.remove(take);

        // 取消其他任务

        for (Future future : futures) {
            future.cancel(true);

        }
        // 关闭线程池
        pool.shutdown();
    }
}
